package com.xneure.database.define;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import com.xneure.database.DataBaseType;
import com.xneure.utils.ObjectUtil;

public abstract class Creator{
	private static Map<String,Class<? extends Creator>> creator = new HashMap<>(5);
	private static ThreadLocal<Creator> currCreator = new ThreadLocal<>();
	private String schema;
	static{
		Creator.register("oracle",OracleCreator.class);
	}

	public Creator(){
	}

	public Creator(DataBaseType type){
		Creator.register(type.getDbName(),getClass());
	}

	public String getSchema(){
		return schema;
	}

	public void setSchema(String schema){
		this.schema = schema;
	}

	protected static void register(String type,Class<? extends Creator> cls){
		creator.put(type,cls);
	}

	public static Creator getCreator(String dbType){
		Creator c = currCreator.get();
		if(null == c){
			if(creator.containsKey(dbType)){
				c = ObjectUtil.newInstance(creator.get(dbType));
				currCreator.set(c);
			}else{
				throw new RuntimeException("不支持的类型：".concat(dbType));
			}
		}
		return c;
	}

	/**
	 * 强制更新表结构
	 * 
	 * @param forced void
	 */
	public abstract void setForcedUpdate(boolean forced);

	/**
	 * 生成创建SQL
	 * 
	 * @param define
	 */
	public abstract String create(TableDefine define);

	public abstract String update(TableDefine define,TableDefine dbDefine);

	public abstract boolean update(Connection conn,TableDefine define,TableDefine dbDefine);

	public abstract boolean update(Connection conn,TableDefine define);

	/**
	 * 根据定义创建表结构 已经存在则自动更新
	 * 
	 * @param conn
	 * @param define
	 */
	public abstract boolean create(Connection conn,TableDefine define);

	protected TableDefine getMetadata(Connection conn,String tableName){
		TableDefineImpl table = null;
		try{
			ResultSet res = conn.createStatement().executeQuery(getTableDefine(tableName));
			if(res.next()){
				table = new TableDefineImpl();
				table.setName(tableName);
				table.setComment(res.getString("tableComment"));
				table.setConstraint(res.getString("tableKey"));
				res = conn.createStatement().executeQuery(getColumnDefine(tableName));
				while(res.next()){
					ColumnDefineImpl col = new ColumnDefineImpl();
					col.setName(res.getString("colName"));
					col.setPrimaryKey("1".equals(res.getString("isKey")));
					col.setType(res.getString("dateType"));
					col.setLength(res.getInt("dataLength"));
					col.setPrecision(res.getInt("dataScale"));
					col.setNullAble("YES".contains(res.getString("isNull")));
					col.setId(res.getInt("id"));
					col.setDefaultValue(res.getObject("defaultValue"));
					col.setComment(res.getString("colComment"));
					table.addColumn(col);
				}
			}
		}catch(SQLException e){
			e.printStackTrace();
		}
		return table;
	}

	protected abstract String getTableDefine(String tableName);

	protected abstract String getColumnDefine(String tableName);
}
